package edu.faytechcc.csc251.elementalTD;

import edu.faytechcc.csc251.elementalTD.towers.Tower;
import java.awt.*;
import javax.swing.*;

/**
 * Builds the buttons that are used for buying towers and placing them and
 * builds status icons score,coins,life,trees
 *
 * @author William Robles
 */
public class GameComponents extends JPanel
{
    private static final int shopWidth = 6;
    private static final int buttonSize = 32;
    private static final int cellSpace = 6;
    private static final int iconSize = 20;
    public static int heldID = -1;
    ;
    private static final int itemBorder = 4;
    public Tower[][] placedTower = new Tower[GameDisplay.map.worldHeight][GameDisplay.map.worldWidth];
    private static int[] buttonId =
    {
        0, 1, 2, -1, -1, -1
    };

    private final Rectangle[] towerButtons = new Rectangle[shopWidth];
    private Rectangle healthIcon;
    private Rectangle moneyIcon;
    private Rectangle treeIcon;

    public GameComponents()
    {
        define();
    }

    /**
     * define method creates all buttons in game
     */
    public void define()
    {

        // Loop to create tower buttons
        for (int i = 0; i < towerButtons.length; i++)
        {
            if (i <= 2)
            {
                towerButtons[i] = new Rectangle(400 + ((buttonSize + cellSpace) * i), 200, buttonSize, buttonSize);
            }
            else if (i <= 5 && i > 2)
            {
                towerButtons[i] = new Rectangle(285 + ((buttonSize + cellSpace) * i), 275, buttonSize, buttonSize);
            }
        }

        healthIcon = new Rectangle(GameDisplay.myWidth - 160, GameDisplay.map.block[0][0].y, iconSize, iconSize);
        moneyIcon = new Rectangle(GameDisplay.map.block[0][13].x + 50, GameDisplay.map.block[0][0].y - 25, iconSize, iconSize);
        treeIcon = new Rectangle(GameDisplay.map.block[0][13].x + 50, GameDisplay.map.block[0][0].y, iconSize, iconSize);
    }

    /**
     * draw method draws all buttons with images attached to them and status
     * information health,coins,score and trees
     *
     * @param g
     */
    public synchronized void draw(Graphics g)
    {
        towerButtons(g);

        statsBar(g);

        if (heldID != -1)
        {
            validPosition(g);

            g.drawImage(Tower.towerList[heldID].texture, GameDisplay.mse.x - ((towerButtons[0].width
                    - (itemBorder * 2)) / 2) + itemBorder, GameDisplay.mse.y - ((towerButtons[0].width
                    - (itemBorder * 2)) / 2) + itemBorder, towerButtons[0].width - (itemBorder * 2),
                    towerButtons[0].height - (itemBorder * 2), null);
        }

        if (GameDisplay.getMobsInGame() != null)
        {
            towerAttack();
        }

        drawTower(g);
    }

    /**
     * click method used to determine which button is clicked by mouse and
     * attaches tower to mouse and places it on map and inside of placedTower
     * array
     *
     * @param mouseEvent
     */
    public void click(int mouseEvent) throws CloneNotSupportedException
    {
        if (mouseEvent == 501)
        {
            for (int i = 0; i < towerButtons.length; i++)
            {
                if (towerButtons[i].contains(GameDisplay.mse))
                {
                    if (buttonId[i] != -1 && Tower.towerList[i].cost <= GameDisplay.playerCash)
                    {
                        heldID = Tower.towerList[i].id;
                    }
                }
            }
        }
        else
        {
            if (heldID != -1)
            {
                for (int y = 0; y < GameDisplay.map.block.length; y++)
                {
                    for (int x = 0; x < GameDisplay.map.block[0].length; x++)
                    {
                        if (GameDisplay.map.block[y][x].contains(GameDisplay.mse)
                                && GameDisplay.map.block[y][x].groundID == GameDisplay.groundGrass
                                && placedTower[y][x] == null)
                        {
                            placedTower[y][x] = (Tower) Tower.towerList[heldID].clone();
                            GameDisplay.playerCash -= Tower.towerList[heldID].cost;
                        }
                    }
                }
                heldID = -1;
            }
        }

    }
    

    /**
     * validPosition draws white box for valid tower spot or red box for invalid
     *
     * @param g
     */
    private void validPosition(Graphics g)
    {
        for (int y = 0; y < GameDisplay.map.block.length; y++)
        {
            for (int x = 0; x < GameDisplay.map.block[0].length; x++)
            {
                if (GameDisplay.map.block[y][x].contains(GameDisplay.mse))
                {
                    if (GameDisplay.map.block[y][x].groundID == GameDisplay.groundGrass
                            && placedTower[y][x] == null)
                    {
                        g.setColor(new Color(255, 255, 255, 150));
                        g.fillRect(GameDisplay.map.block[0][x].x, GameDisplay.map.block[y][0].y,
                                GameDisplay.map.block[y][x].width, GameDisplay.map.block[y][x].height);
                    }
                    else
                    {
                        g.setColor(new Color(255, 0, 0, 150));
                        g.fillRect(GameDisplay.map.block[0][x].x, GameDisplay.map.block[y][0].y,
                                GameDisplay.map.block[y][x].width, GameDisplay.map.block[y][x].height);
                    }
                }
            }
        }
    }

    /**
     * towerRadius displays the attack radius
     *
     * @param g
     */
    private void drawTower(Graphics g)
    {
        for (int y = 0; y < GameDisplay.map.block.length; y++)
        {
            for (int x = 0; x < GameDisplay.map.block[0].length; x++)
            {
                if (this.placedTower[y][x] != null)
                {
                    // draws tower radius
                    g.setColor(Color.GRAY);
                    g.drawOval(GameDisplay.map.blockSize / 2 + GameDisplay.map.block[y][x].x
                            - ((placedTower[y][x].range * GameDisplay.map.blockSize) / 2),
                            GameDisplay.map.blockSize / 2 + GameDisplay.map.block[y][x].y
                            - ((placedTower[y][x].range * GameDisplay.map.blockSize) / 2),
                            (placedTower[y][x].range * GameDisplay.map.blockSize),
                            (placedTower[y][x].range * GameDisplay.map.blockSize));
                    // fills tower radius
                    g.setColor(new Color(64, 64, 64, 45));
                    g.fillOval(GameDisplay.map.blockSize / 2 + GameDisplay.map.block[y][x].x
                            - ((placedTower[y][x].range * GameDisplay.map.blockSize) / 2),
                            GameDisplay.map.blockSize / 2 + GameDisplay.map.block[y][x].y
                            - ((placedTower[y][x].range * GameDisplay.map.blockSize) / 2),
                            (placedTower[y][x].range * GameDisplay.map.blockSize),
                            (placedTower[y][x].range * GameDisplay.map.blockSize));

                    g.drawImage(Tower.towerList[placedTower[y][x].id].texture, GameDisplay.map.block[y][x].x,
                            GameDisplay.map.block[y][x].y, GameDisplay.map.blockSize,
                            GameDisplay.map.blockSize, null);

                    if (placedTower[y][x].target != null)
                    {
                        g.setColor(Color.RED);
                        g.drawLine(this.placedTower[y][x].towerX + (GameDisplay.map.blockSize / 2),
                                this.placedTower[y][x].towerY + (GameDisplay.map.blockSize / 2),
                                this.placedTower[y][x].target.x + (GameDisplay.map.blockSize / 2),
                                this.placedTower[y][x].target.y + (GameDisplay.map.blockSize / 2));
                    }

                }
            }
        }

    }

    /**
     * towerAttack method scans map for inRange creeps and fires if mob is in
     * range
     */
    private void towerAttack()
    {

        for (int y = 0; y < GameDisplay.map.block.length; y++)
        {
            for (int x = 0; x < GameDisplay.map.block[0].length; x++)
            {
                if (this.placedTower[y][x] != null)
                {
                    if (this.placedTower[y][x].target == null)
                    {
                            Mob selectTarget = this.placedTower[y][x].targetedEnemy(GameDisplay.getMobsInGame(), y, x);
                            if (this.placedTower[y][x].attackReload > this.placedTower[y][x].MaxAttackReload)
                            {
                                if (selectTarget != null)
                                {
                                    selectTarget.damageMob(this.placedTower[y][x].damage);
                                    this.placedTower[y][x].target = selectTarget;
                                    this.placedTower[y][x].attackCounter = 0;
                                    this.placedTower[y][x].attackReload = 0;
                                }

                            }
                            else
                            {
                                this.placedTower[y][x].attackReload += 1;
                            }
                        }
                        else
                        {
                            if (this.placedTower[y][x].attackCounter < this.placedTower[y][x].MaxAttackCounter)
                            {
                                this.placedTower[y][x].attackCounter += 1;
                            }
                            else
                            {
                                this.placedTower[y][x].target = null;
                            }
                        }
                }
            }
        }
    }

    /**
     * statsBar method builds the status bar information
     *
     * @param g
     */
    private void statsBar(Graphics g)
    {
        // Draws/setups health info
        g.drawImage(GameDisplay.tile_statusIcons[1], healthIcon.x, healthIcon.y, healthIcon.width, healthIcon.height, null);
        g.setFont(new Font("Courier New", Font.BOLD, 16));
        g.setColor(Color.RED);
        g.drawString("" + GameDisplay.playerHealth, healthIcon.x + healthIcon.width + 5, healthIcon.y + 15);

        // Draws/setups money info
        g.drawImage(GameDisplay.tile_statusIcons[0], moneyIcon.x, moneyIcon.y, moneyIcon.width, moneyIcon.height, null);
        g.setColor(Color.YELLOW);
        g.drawString("" + GameDisplay.playerCash, moneyIcon.x + moneyIcon.width + 5, moneyIcon.y + 15);

        // Draws/setups tree info
        g.drawImage(GameDisplay.tile_statusIcons[2], treeIcon.x, treeIcon.y, treeIcon.width, treeIcon.height, null);
        g.setColor(Color.GREEN);
        g.drawString("" + GameDisplay.playerTree, treeIcon.x + treeIcon.width + 5, treeIcon.y + 15);

        // Draws/setups text info        
        g.setColor(Color.WHITE);
        g.drawString("Score" + " " + GameDisplay.playerScore, healthIcon.x, moneyIcon.y + 15);
    }

    /**
     * towerButtons method builds the tower buttons
     *
     * @param g
     */
    private void towerButtons(Graphics g)
    {
        // Creates tower buttons for shop
        for (int i = 0; i < towerButtons.length; i++)
        {
            if (i <= 2)
            {
                if (towerButtons[i].contains(GameDisplay.mse))
                {
                    g.setColor(new Color(255, 255, 255, 170));
                    g.fillRect(towerButtons[i].x, towerButtons[i].y, towerButtons[i].width, towerButtons[i].height);
                }

                // Draws top shop buttons
                g.drawImage(GameDisplay.tile_shopButton[0], towerButtons[i].x, towerButtons[i].y, towerButtons[i].width, towerButtons[i].height, null);

                // Draws top shop items in buttons
                g.drawImage(Tower.towerList[i].texture, towerButtons[i].x + itemBorder, towerButtons[i].y + itemBorder,
                        towerButtons[i].width - (itemBorder * 2), towerButtons[i].height - (itemBorder * 2), null);

                if (Tower.towerList[i].cost > GameDisplay.playerCash)
                {
                    g.setColor(new Color(30, 30, 30, 170));
                    g.fillRect(towerButtons[i].x, towerButtons[i].y, towerButtons[i].width, towerButtons[i].height);
                }
            }
            else if (i <= 5 && i > 2)
            {
                if (towerButtons[i].contains(GameDisplay.mse))
                {
                    g.setColor(new Color(255, 255, 255, 100));
                    g.fillRect(towerButtons[i].x, towerButtons[i].y, towerButtons[i].width, towerButtons[i].height);
                }

                // Draws lower shop buttons
                g.drawImage(GameDisplay.tile_shopButton[0], towerButtons[i].x, towerButtons[i].y, towerButtons[i].width, towerButtons[i].height, null);

                if (buttonId[i] != -1)
                {
                    // Draws lower shop items in buttons
                    g.drawImage(GameDisplay.upperLevel[buttonId[i]], towerButtons[i].x + itemBorder, towerButtons[i].y + itemBorder,
                            towerButtons[i].width - (itemBorder * 2), towerButtons[i].height - (itemBorder * 2), null);
                }
            }

        }
    }
}
